package top.healthylife.gateway.platform.td.api.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import top.healthylife.basics.utils.exception.BusinessException;
import top.healthylife.basics.utils.utils.SystemThreadLocal;
import top.healthylife.gateway.core.util.SystemConfigUtils;
import top.healthylife.gateway.dto.request.req.ApiReqDto;
import top.healthylife.gateway.platform.td.api.config.SystemConfig;
import top.heathylife.gateway.common.cons.SystemCons;
import top.heathylife.gateway.common.po.RecordRequestInfo;

import java.util.HashMap;
import java.util.Map;


/**
 * @author cl
 * @version 1.0
 * @date 2020/4/30 10:43
 */
@Slf4j
public class TdUtils {

    public static final String SUCCESS = "success";
    public static final String REASON_DESC = "reason_desc";
    public static final String RESULT_DESC = "result_desc";
    public static final String PRO_DOMAIN = "https://api.tongdun.cn";
    public static final String SIT_DOMAIN = "https://apitest.tongdun.cn";
    /**
     * 信贷类接口
     */
    public static final String CREDIT_BODYGUARD = "/bodyguard/apply/v5";
    public static final Map<String, String> RESPONSE_MAP = new HashMap<>();
    public static final String SIT = "SIT";
    public static final String PRO = "PRO";
    public static String POST = "POST";
    public static String GET = "GET";

    static {
        RESPONSE_MAP.put("000", "认证失败,因系统认证引起的其他未知错误");
        RESPONSE_MAP.put("001", "用户认证失败,合作方标识和合作方密钥认证失败");
        RESPONSE_MAP.put("101", "参数不能为空");
        RESPONSE_MAP.put("415", "不支持的媒体类型,Content-Type与接口要求不一致");
        RESPONSE_MAP.put("500", "内部错误,因内部执行错误引起的其他未知错误");
        RESPONSE_MAP.put("600", "合作方限流,ngxQPS达到上线");
        RESPONSE_MAP.put("610", "合作方IP白名单,ngx访问受限");
        RESPONSE_MAP.put("6001", "流程执行异常终止,请调用重试接口恢复异常");
        RESPONSE_MAP.put("9000", "应用未配置行业或未勾选模块,应用未配置行业或未勾选模块");
        RESPONSE_MAP.put("9001", "未找到相应工作流配置,一条工作流都没有配置或者传了biz_code但是传的不对或者app_name不对");
        RESPONSE_MAP.put("9004", "不处于数据补充状态,数据补充接口已经调用过,或者传入的id不正确");
        RESPONSE_MAP.put("9005", "不处于决策复议状态,决策复议接口已经调用过,或者传入的id不正确");
        RESPONSE_MAP.put("9006", "不处于异常补救状态,异常补救接口已经调用过,或者传入的id不正确");
        RESPONSE_MAP.put("9007", "不处于暂停状态,暂停接口已经调用过, 或者传入的id不正确");
        RESPONSE_MAP.put("9008", "根据合作方,应用ID找不到可执行的工作流");
        RESPONSE_MAP.put("9009", "调用异常,请联系售后");
        RESPONSE_MAP.put("9010", "数据补充模块获取不到数据");
        RESPONSE_MAP.put("9011", "对不起,重试次数已到达上限或时限已过");
        RESPONSE_MAP.put("9012", "流程执行异常,由于未知错误导致工作流执行异常");
        RESPONSE_MAP.put("9013", "身份证号有误,");
        RESPONSE_MAP.put("9016", "用户信息解密失败");
        RESPONSE_MAP.put("9017", "不处于决策补充状态,决策补充接口已经调用过或者传入的id不正确");
        RESPONSE_MAP.put("9018", "加密字段的值与选择的加密方式不一致,比如选了MD5或SHA256的方式加密");
        RESPONSE_MAP.put("9019", "不处于智能信审答题状态,答题接口已经调用过");
        RESPONSE_MAP.put("9020", "记录已过期,记录已过期");
        RESPONSE_MAP.put("9021", "工作流执行异常,请联系客服查看工作流配置");
        RESPONSE_MAP.put("630", "未找到贷前查询记录,贷中核查");
        RESPONSE_MAP.put("9022", "接口版本过低,请联系客服");
    }

    @SneakyThrows
    public static JSONObject tongDunHttpRequest(ApiReqDto tdDto, String url, String requestMethod) {
        return tongDunHttpRequest(tdDto, url, requestMethod, null);
    }

    @SneakyThrows
    public static JSONObject tongDunHttpRequest(ApiReqDto tdDto, String url, String requestMethod, String bizCode) {
        log.info("收到请求参数为:{}", JSONObject.toJSONString(tdDto));
        //1.获取账号信息
        SystemConfig systemConfig = getSystemConfigInfo();
        log.info("收到请求参数为:{}", JSONObject.toJSONString(systemConfig));
        //2.获取接口请求地址
        String apiUrl = getFinalUrlByEnv(systemConfig, url);

        String params;
        String finalUrl;
        String responseBody = null;
        Map<String, Object> map = BeanUtil.beanToMap(systemConfig);
        //去除环境参数
        map.remove("env");
        log.info("当前接口请求方式:{}", requestMethod);

        if (GET.equals(requestMethod)) {
            //3.1请求地址拼接账号参数
            //3.2 get请求额外拼接查询参数
            Map<String, Object> dtoMap = BeanUtil.beanToMap(tdDto);
            dtoMap.put("biz_code", bizCode);
            map.putAll(camel2UnderLine(dtoMap));
            params = spliceParam(map);
            finalUrl = apiUrl + params;
            RecordRequestInfo.recordRequest(finalUrl, null, null, "get");
            responseBody = HttpUtil.createGet(finalUrl).execute().body();
        }

        if (POST.equals(requestMethod)) {
            params = spliceParam(map);
            Map<String, Object> dtoMap = BeanUtil.beanToMap(tdDto);
            dtoMap.put("biz_code", bizCode);
            Map<String, Object> dtoMapUnderLine = camel2UnderLine(dtoMap);
            finalUrl = apiUrl + params;
            RecordRequestInfo.recordRequest(finalUrl, JSONUtil.toJsonStr(dtoMapUnderLine), null, "post");
            responseBody = HttpUtil.createPost(finalUrl).form(dtoMapUnderLine).execute().body();
        }

        log.info("收到同盾响应结果:{}", responseBody);
        try {
            JSONObject jsonObject = JSONObject.parseObject(responseBody);
            //将三方元数据存储到线程变量
            SystemThreadLocal.set(SystemCons.ORIGIN_DATA,jsonObject.toJSONString());
            String flag = jsonObject.getString(SUCCESS);
            //监控类接口
            if (!CREDIT_BODYGUARD.equalsIgnoreCase(url)) {
                //调用成功
                if (Boolean.TRUE.toString().equals(flag)) {
                    return jsonObject;
                } else {
                    //调用失败
                    String message = jsonObject.getString(REASON_DESC);
                    throw new BusinessException(message);
                }
            } else {
                //信贷类接口
                 return jsonObject;
            }
        } catch (Exception e) {
            throw new BusinessException("同盾响应结果异常:{}", e.getMessage());
        }

    }

    private static SystemConfig getSystemConfigInfo() {
        //获取配置信息
        return (SystemConfig) SystemConfigUtils.get();
    }

    private static String getFinalUrlByEnv(SystemConfig systemConfig, String url) {
        String env = systemConfig.getEnv();
        if (SIT.equalsIgnoreCase(env)) {
            return SIT_DOMAIN + url;
        } else if (PRO.equalsIgnoreCase(env)) {
            return PRO_DOMAIN + url;
        } else {
            throw new BusinessException("获取环境信息错误,期望在[SIT,PRO],实际是{}", env);
        }
    }

    private static String spliceParam(Map<String, Object> paramsMap) {
        StringBuilder stringBuilder = new StringBuilder().append("?");
        paramsMap.forEach((k, v) -> {
            if (v != null) {
                stringBuilder.append(k).append("=").append(v).append("&");
            }
        });
        String str = stringBuilder.toString();
        //移除最后一个&
        return str.substring(0, str.length() - 1);
    }

    /**
     * map的key转下划线
     *
     * @param map map
     * @return 转换后的map
     */
    private static Map<String, Object> camel2UnderLine(Map<String, Object> map) {
        Map<String, Object> newMap = new HashMap<>(map.size());
        map.forEach((k, v) -> newMap.put(StrUtil.toUnderlineCase(k), v));
        return newMap;
    }
}
